package com.usian.admin.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.usian.admin.entity.AdChannel;
import com.usian.admin.service.AdChannelService;
import com.usian.admin.service.IAdSensitiveService;
import com.usian.admin.service.WemediaNewsAutoService;
import com.usian.article.client.ArticleFeign;
import com.usian.common.aliyun.GreenImageScan;
import com.usian.common.aliyun.GreenTextScan;
import com.usian.common.dtos.PageResult;
import com.usian.common.dtos.ResponseResult;
import com.usian.common.enums.AppHttpCodeEnum;
import com.usian.common.exception.LeadException;
import com.usian.common.util.JsonUtils;
import com.usian.common.util.SensitiveWordUtil;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.media.dtos.WmNewsDto;
import com.usian.model.media.dtos.WmNewsResultDTO;
import com.usian.wemedia.client.WemediaFeign;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

import static com.usian.common.constants.message.Article2EsConstants.ARTICLE_2_ES_TOPIC;

@Service
public class WemediaNewsAutoServiceImpl implements WemediaNewsAutoService {

    @Autowired
    private WemediaFeign wemediaFeign;

    @Autowired
    private IAdSensitiveService adSensitiveService;

    @Autowired
    private GreenTextScan textScan;

    @Autowired
    private GreenImageScan imageScan;

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private AdChannelService adChannelService;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Override
    @GlobalTransactional
    public void auditWemediaNews(Integer wmNewId) {
        if(wmNewId==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //        远程调用-wemedia服务，根据wmNewsId查询自媒体文章信息
        ResponseResult<WmNewsResultDTO> responseResult = wemediaFeign.findById(wmNewId);
        WmNewsResultDTO dto = responseResult.getData();
        //参数校验
        if(dto ==null || responseResult.getCode()!=0){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章数据不存在");
        }
        //        判断自媒体文章状态，进行操作
        Integer status = dto.getStatus();
        //如果是 1 -待审核
        if(status==1){
            //获取自媒体文章的文本内容以及图片列表（包含封面图片）
            Map<String,Object> contentMap = getTextAndImage(dto.getTitle(),dto.getContent(),dto.getImages());
            //查询所有敏感词
            List<String> sensitiveList = adSensitiveService.findAll();
            //DFA算法进行自定义敏感词审核
            Boolean b = handleSensitive(String.valueOf(contentMap.get("text")),sensitiveList,wmNewId);
            if(!b){
                return;
            }

            //               调用阿里云的接口审核文字
            Boolean b1 = handleTextScan(String.valueOf(contentMap.get("text")),wmNewId);
            if(!b1){
                return;
            }

            //               调用阿里云的接口审核图片
            Boolean b2 = handleImageScan((List<String>)contentMap.get("image"),wmNewId);
            if(!b2){
                return;
            }
            //3.4 审核通过，远程调用自媒体微服务修改自媒体文章状态
            updateWmNews(wmNewId,"通过",WmNewsResultDTO.Status.SUCCESS.getCode());
        }

        //判断发布时间是否存在，并且发布时间大于当前时间，什么都不需要做
        if(dto.getPublishTime()!=null && dto.getPublishTime().getTime()>new Date().getTime()){
            return;
        }

        //如果是4人工审核通过或者是8审核通过（待发布），或者没有发布时间，需要更新自媒体文章状态为9已发布
        updateWmNews(wmNewId,"发布文章",WmNewsResultDTO.Status.PUBLISHED.getCode());

        //查询频道名称，封装到自媒体文章中
        AdChannel adChannel = adChannelService.getById(dto.getChannelId());
        if(adChannel!=null){
            dto.setChannelName(adChannel.getName());
        }
        //同步自媒体文章为App文章
        Long articleId = articleFeign.saveArticle(dto);
        //生产消息，同步审核通过的文章到索引库
        kafkaTemplate.send(ARTICLE_2_ES_TOPIC,articleId);
    }

    @Override
    public void auditWmNewsTask() {
        //通过feign远程调用，查询待发布的自媒体文章id列表
        List<Integer> wmNewsIds = wemediaFeign.findWmNewsIds();
        for (Integer wmNewsId : wmNewsIds) {
            //自动审核，并发布文章
            auditWemediaNews(wmNewsId);
        }
    }

    @Override
    public PageResult<WmNewsResultDTO> findWmNewsPage(NewsAuthDto dto) {
        PageResult<WmNewsResultDTO> pageResult = wemediaFeign.findWmNewsPage(dto);
        return pageResult;
    }

    @Override
    public ResponseResult<WmNewsResultDTO> findWmNewsById(Integer id) {
        ResponseResult<WmNewsResultDTO> responseResult = wemediaFeign.findById(id);
        return responseResult;
    }

    /**
     * 调用阿里云的接口审核图片
     * @param imageList
     * @param wmNewId
     * @return
     */
    private Boolean handleImageScan(List<String> imageList, Integer wmNewId) {
        try {
            //调用阿里云的接口审核图片
            Map<String, String> map = imageScan.imageScan(imageList);
            if(CollectionUtils.isEmpty(map)){
                //没有返回内容，说明可能没有检查，抛异常
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"调用阿里云文本反垃圾异常");
            }
            //获取阿里云返回的建议suggestion
            String suggestion = map.get("suggestion");
            if("pass".equals(suggestion)){
                //审核通过
                return true;
            }
            //审核未通过或进一步人工审核
            Integer status = "review".equals(suggestion) ? WmNewsResultDTO.Status.ADMIN_AUTH.getCode() : WmNewsResultDTO.Status.FAIL.getCode();
            //更新自媒体文章状态
            updateWmNews(wmNewId,map.get("label"),status);
            return false;

        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"调用阿里云图片反垃圾异常");
        }
    }

    /**
     * 调用阿里云的接口文本审核
     * @param text
     * @param wmNewId
     * @return
     */
    private Boolean handleTextScan(String text, Integer wmNewId) {
        try {
            //调用阿里云文本反垃圾接口
            Map<String, String> map = textScan.greenTextScan(text);
            if(CollectionUtils.isEmpty(map)){
                //没有返回内容，说明可能没有检查，抛异常
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"调用阿里云文本反垃圾异常");
            }
            //获取阿里云返回的建议suggestion
            String suggestion = map.get("suggestion");
            if("pass".equals(suggestion)){
                //审核通过
                return true;
            }
            //审核未通过或进一步人工审核
            Integer status = "review".equals(suggestion) ? WmNewsResultDTO.Status.ADMIN_AUTH.getCode() : WmNewsResultDTO.Status.FAIL.getCode();
            //更新自媒体文章状态
            updateWmNews(wmNewId,map.get("reson"),status);
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"调用阿里云文本反垃圾异常");
        }

    }

    /**
     * 自定义敏感词审核
     * @param text
     * @param sensitiveList
     * @param wmNewId
     * @return
     */
    private Boolean handleSensitive(String text, List<String> sensitiveList, Integer wmNewId) {
        Map<String, Integer> map = SensitiveWordUtil.matchWords(sensitiveList, text);
        if(!CollectionUtils.isEmpty(map)){
            //文本中存在自定义敏感词，审核失败，更新自媒体文章状态
            updateWmNews(wmNewId,"存在敏感词",WmNewsResultDTO.Status.FAIL.getCode());
            return false;
        }
        return true;

    }

    /**
     * 更新自媒体文章状态
     * @param wmNewId
     * @param reason
     * @param code
     */
    @Override
    public void updateWmNews(Integer wmNewId, String reason, Integer code) {
        WmNewsDto wmNewsDto = new WmNewsDto();
        wmNewsDto.setId(wmNewId);
        wmNewsDto.setReason(reason);
        wmNewsDto.setStatus(code);
        wemediaFeign.updateWmNews(wmNewsDto);
    }

    /**
     * 获取自媒体文章的文本内容以及图片列表
     * @param title
     * @param content
     * @param images
     * @return
     */
    private Map<String, Object> getTextAndImage(String title, String content, String images) {
        //参数校验
        if(StringUtils.isBlank(title) || StringUtils.isBlank(content)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"文章标题和内容不能为空");
        }
        //数据组装
        //解析content正文信息
        List<Map<String, String>> mapList = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, String>>>() {});
        //拼接文本内容
        StringBuilder stringBuilder = new StringBuilder();
        //拼接标题
        stringBuilder.append(title);
        //封装图片列表的集合
        List<String> imageUrlList = new ArrayList<>();
        for (Map<String, String> map : mapList) {
            //判断是否是文本
            String type = map.get("type");
            if("text".equals(type)){
                stringBuilder.append(map.get("value"));
            }
            //封装图片信息
            if("image".equals(type)){
                imageUrlList.add(map.get("value"));
            }
        }

        //处理封面图片
        if(StringUtils.isNotBlank(images)){
            //获取封面图片列表
            List<String> list = Arrays.asList(images.split(","));
            imageUrlList.addAll(list);
        }

        //封装结果
        Map<String, Object> map = new HashMap<>();
        map.put("text",stringBuilder);
        map.put("image",imageUrlList);
        return map;

    }
}
